package language.advanced.reflect.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class newProxyInstanceTest {
    //接口里的方法多了。用静态代理就会很麻烦。
    //用动态代理，不管接口里有多个方法，都可以
    interface A{
        void sayHello();
        void sayWorld();
    }

    static class AImpl implements A{
        @Override
        public void sayHello(){
            System.out.println("hello");
        }

        @Override
        public void sayWorld() {
            System.out.println("world");
        }


    }

    static class DynamicProxy2 implements InvocationHandler{
        Object object;
        Object bind(Object object){
            this.object = object;
            return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
        }

        @Override
        // 加在原先方法前面/后面要执行的代码。这个对所有的方法都是一样的。执行统一的逻辑
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before welcome");
            Object rs = method.invoke(object, args);
            System.out.println("after welcome");
            return rs;
        }
    }

    public static void main(String[] args){
        //生成$Proxy0的class文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

        //指定一个接口，可以方便调用，不用通过反射去执行方法
        A proxy = (A) new DynamicProxy2().bind(new AImpl());
        //这里已经生成了一个$Proxy0类的实例proxy。
        // $Proxy0类是一个实现了A接口的类。实现了A接口的所有方法。还有一个属性h是DynamicProxy2的实例
        // 而每个proxy的方法执行this.h.invoke(this,m3,null)；相当于执行DynamicProxy2.invoke (非反射调用)
        // m3被初始化为Class.forName(...DynamicProxy2...).getMethod("sayHello",new Class[0])
        // new Class[0]表示有零个元素的Class数组，即空数组，与传入null结果是一样的，都表示取得无参构造方法。
        proxy.sayHello();
        proxy.sayWorld();

        //sun.reflect.Reflection
    }
}



